#include "TrueText/Config.h"
#include "FaceImpl.h"
#include "ftutils.h"
#include "TrueText/Stream.h"
#include "StreamImpl.h"
#include "ftcache.h"
#include <boost/bind.hpp>

namespace TrueText {

FaceImpl::FaceImpl(const FaceImpl& rhs)
	: face(rhs.face)
	, id(rhs.id)
{ 
	FT_Reference_Face(face);
}

const FaceImpl& FaceImpl::operator=(const FaceImpl& rhs)
{ 
	if (this == &rhs)
		return *this;

	face = rhs.face;
	FT_Reference_Face(face);
	id = rhs.id;

	return *this;
}

FaceImpl::~FaceImpl()
{
}

namespace {

void StreamClose(FT_Stream stream)
{
	GetFaceIdManager()->ClosingStream(stream);
}

FT_Face FaceLoader(boost::function<boost::shared_ptr<Stream> ()> dataLoader)
{
	boost::shared_ptr<Stream> data = dataLoader();

	FT_Open_Args openArgs;
	memset(&openArgs, 0, sizeof(openArgs));

	openArgs.flags = FT_OPEN_STREAM;
	openArgs.stream = data->getImpl()->GetStream();

	if (openArgs.stream->close)
		TT_FAIL("Custom stream destructors not implemented yet.");

	openArgs.stream->close = &StreamClose;
	GetFaceIdManager()->RegisterStream(openArgs.stream, data);

	FT_Face face;
	FT_EH(FT_Open_Face(GetLibraryHandle(), &openArgs, 0, &face));

	new boost::shared_ptr<Stream>(data);

	return face;
}

} // anonymous namespace

FaceImpl::FaceImpl(std::string id, boost::function<boost::shared_ptr<Stream> ()> dataLoader)
{
	FaceId* faceId = GetFaceIdManager()->GetFaceId(id, boost::bind(&FaceLoader, dataLoader));
	this->id = faceId;

	FT_EH(FTC_Manager_LookupFace(GetFtcManager(), reinterpret_cast<FTC_FaceID>(faceId), &this->face));
}

std::string FaceImpl::GetFamilyName() const
{
	return getFace()->family_name;
}

std::string FaceImpl::GetStyleName() const
{
	return getFace()->style_name;
}

}